<template>
  <v-data-table
    v-bind="proxyAttrs"
    v-on="proxyListeners"
    :server-items-length="totalItem"
    :options.sync="queryOptions"
    :headers="headers"
    :items="items"
    :loading="loading"
    :loading-text="loadingText"
  >
    <template v-for="(_, slot) of $scopedSlots" v-slot:[slot]="scope">
      <slot :name="slot" v-bind="scope" />
    </template>
  </v-data-table>
</template>

<script>
  // 封装对列表服务器端分页，搜索查询，以及排序等操作
  // 引入这个mixin的组件应该定义headers变量，
  // 对应不能搜索的字段，在headers里设置sortable: false
  // 不支持排序的字段，在headers里设置filterable: false
  export default {
    name: "DataTableServer",
    functional: false,
    props: {
      queryBackendFunc: {
        // 传入获取数据的函数，接收query_args, page, per_page三个参数
        // 返回一个含{results, total}的对象
        // results为列表结果，total为结果总数
        type: Function,
        required: true,
      },
      headers: {
        // 表格表头数组
        type: Array,
        required: true,
      },
      loadingText: {
        // 加载过程中的文字
        type: String,
        required: false,
        default: "加载中",
      },
      search: {
        // 搜索关键词
        type: String,
        required: false,
        default: "",
      },
      searchableProps: {
        // 可搜索的属性，如果不传，则从headers中读取
        // 对应不能搜索的字段，在headers里设置filterable: false
        // 后台接口需支持like查询
        type: Array,
        required: false,
        default: () => [],
      },
      sortableProps: {
        // 支持排序的字段，如果不传，则从headers中读取
        // 对应不支持排序字段，在headers里设置sortable: false
        // 后台接口需支持order和order_by查询
        type: Array,
        required: false,
        default: () => [],
      },
      getDataTrigger: {
        // 用于改变值后台获取数据
        type: Boolean,
        required: false,
        default: false,
      },
    },
    data: () => ({
      loading: false,
      items: [], // 绑定到datatable的列表值
      queryOptions: {
        itemsPerPage: 10,
        page: 1,
        sortBy: [],
        sortDesc: [],
      },
      totalItem: 0,
    }),
    computed: {
      localSearchableProps() {
        if (this.searchableProps && this.searchableProps.length > 0) {
          return this.searchableProps
        } else {
          const searchable_props = this.headers
            .filter((x) => x.filterable !== false)
            .map((x) => x.value)
          return searchable_props
        }
      },
      localSortableProps() {
        if (this.sortableProps && this.sortableProps.length > 0) {
          return this.sortableProps
        } else {
          const sortable_props = this.headers
            .filter((x) => x.sortable !== false)
            .map((x) => x.value)
          return sortable_props
        }
      },
      proxyAttrs() {
        const {
          headers: headers,
          loading: loading,
          loadingText: loadingText,
          items: items,
          options: queryOptions,
          serverItemsLength: totalItem,
          ...others
        } = this.$attrs
        return others
      },
      proxyListeners() {
        const { "update:options": updateOptions, ...others } = this.$listeners
        return others
      },
    },
    watch: {
      queryOptions: {
        handler(val, oldVal) {
          this.getData()
        },
        deep: true,
      },
      getDataTrigger: {
        handler() {
          this.getData()
        },
        immediate: true,
      },
    },
    methods: {
      getData() {
        this.loading = true
        let query_args = {}

        // if (this.search && this.search.length > 0) {
        //   // TODO, or query
        //   // 支持按多个关键词分开的查询条件
        //   const search_keywords = this.search.split(" ")
        //   for (const prop of this.localSearchableProps) {
        //     for (const keyword of search_keywords) {
        //       query_args[`${prop}_like`] = keyword
        //     }
        //   }
        // }

        if (this.queryOptions.sortBy && this.queryOptions.sortBy.length > 0) {
          let sortby = []
          let sortbydesc = []
          for (let i = 0; i < this.queryOptions.sortBy.length; i++) {
            const sortby_prop = this.queryOptions.sortBy[i]
            if (this.localSortableProps.includes(sortby_prop)) {
              if (this.queryOptions.sortDesc[i]) {
                sortbydesc.push(sortby_prop)
              } else {
                sortby.push(sortby_prop)
              }
            }
          }
          if (sortby.length > 0) {
            query_args.order_by = sortby.join(",")
          }
          if (sortbydesc.length > 0) {
            query_args.order_by_desc = sortbydesc.join(",")
          }
        }

        this.queryBackendFunc(
          query_args,
          this.queryOptions.page,
          this.queryOptions.itemsPerPage
        ).then((result) => {
          this.loading = false
          this.items = result.results
          this.totalItem = result.total
        })
      },
    },
  }
</script>
